package com.base.mvvm

import android.util.ArrayMap
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.ViewModelProvider
import java.util.LinkedList

/**
 * @describe:
 * @Author: lixiaopeng
 * @Date: 12/3/20
 */
object BindViewModelProcess {
    private val activityViewModel = ArrayMap<FragmentActivity, LinkedList<BaseViewModel>>()
    private val fragmentViewModel = ArrayMap<Fragment, LinkedList<BaseViewModel>>()

    fun bind(activity: FragmentActivity) {
        val aClass: Class<out FragmentActivity?> = activity.javaClass
        val fields = aClass.declaredFields
        val baseViewModels = LinkedList<BaseViewModel>()
        for (field in fields) {
            val viewModel = field.getAnnotation(BindViewModel::class.java)
            if (viewModel != null) {
                field.isAccessible = true
                val type = field.type as Class<BaseViewModel>
                try {
                    val instance = ViewModelProvider.AndroidViewModelFactory.getInstance(activity.application)
                    val value = ViewModelProvider(activity, instance).get<BaseViewModel>(type)
                    val base = value
                    activity.lifecycle.addObserver(base)
                    baseViewModels.add(base)
                    field[activity] = value
                } catch (e: IllegalAccessException) {
                    e.printStackTrace()
                }
            }
        }
        activityViewModel[activity] = baseViewModels
    }

    fun bind(fragment: Fragment) {
        val activity = fragment.activity ?: return
        val aClass: Class<out Fragment?> = fragment.javaClass
        val fields = aClass.declaredFields
        val baseViewModels = LinkedList<BaseViewModel>()
        for (field in fields) {
            val viewModel = field.getAnnotation(BindViewModel::class.java)
            if (viewModel != null) {
                field.isAccessible = true
                val type = field.type as Class<BaseViewModel>
                try {
                    val instance = ViewModelProvider.AndroidViewModelFactory.getInstance(activity.application)
                    val value = ViewModelProvider(fragment, instance).get<BaseViewModel>(type)
                    val base = value
                    activity.lifecycle.addObserver(base)
                    baseViewModels.add(base)
                    field[fragment] = value
                } catch (e: IllegalAccessException) {
                    e.printStackTrace()
                }
            }
        }
        fragmentViewModel[fragment] = baseViewModels
    }

    fun unbind(activity: FragmentActivity) {
        val baseViewModels = activityViewModel[activity]
        if (baseViewModels != null && !baseViewModels.isEmpty()) {
            for (model in baseViewModels) {
                activity.lifecycle.removeObserver(model)
            }
        }
        activityViewModel.remove(activity)
    }

    fun unbind(fragment: Fragment) {
        val baseViewModels = fragmentViewModel[fragment]
        if (baseViewModels != null && !baseViewModels.isEmpty()) {
            for (model in baseViewModels) {
                fragment.lifecycle.removeObserver(model)
            }
            fragmentViewModel.remove(fragment)
        }
    }
}